package com.xtt.dynamic.service.impl;


import com.xtt.dynamic.entity.Friend;
import com.xtt.dynamic.mapper.r.ReadFriendMapper;
import com.xtt.dynamic.mapper.w.WriteFriendMapper;
import com.xtt.dynamic.service.FriendService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;

@Service
public class FriendServiceImpl implements FriendService {

    @Autowired
    private ReadFriendMapper readFriendMapper;

    @Autowired
    private WriteFriendMapper writeFriendMapper;

    @Autowired
    private TransactionTemplate wTransactionTemplate;

    @Autowired
    private TransactionTemplate rTransactionTemplate;

    //读--读库
    @Override
    public List<Friend> list() {
        return readFriendMapper.list();
    }

    //写-写库
    @Override
    public void save(Friend friend) {
        writeFriendMapper.save(friend);
    }

    //保存 -写库
    @Override
    public void saveW(Friend friend) {
        friend.setName("李寒衣W");
        writeFriendMapper.save(friend);
    }

    //保存-读库
    @Override
    public void saveR(Friend friend) {
        friend.setName("李寒衣R");
        readFriendMapper.save(friend);
    }
    //读-写
    //这种方式只能针对一个事务管理器进行控制，无法完成多数据源控制
    //特殊情况：
    // 1.如果是主库出现异常   可以
    // 2.从库出现异常 可以
    // 3.异常出现在主库和从库的中间
    // 除非在主库和从库进行的业务出现了异常，就不能保证事务一致性
//    @Transactional
//    @Override
//    public void saveAll(Friend friend) {
//        saveW(friend);
//        saveR(friend);
//        int a=1/0;
//    }
    //通过Spring编程式事务实现不同的数据源控制
    @Override
    public void saveAll(Friend friend) {
        wTransactionTemplate.execute(wStatus -> {
            rTransactionTemplate.execute(rStatus->{
                try{
                    saveW(friend);
                    saveR(friend);
                    int a = 1 / 0;
                }catch (Exception e){
                    e.printStackTrace();
                    wStatus.setRollbackOnly();
                    rStatus.setRollbackOnly();
                    return false;
                }
                return true;
            });
            return true;
        });
    }
}
